<template>
    <MyArticle title="Java学习笔记之二：对象与类" date="2024年02月21日">
        <div class="_article-content">
            <p>面向对象程序设计（OOP：Object-Oriented Programming）是当今的主流程序设计范型。面向对象的程序是由对象组成的，每个对象包含对用户公开的特定功能和隐藏的实现。</p>
            <p>类（class）指定了如何构造对象，由一个类构造（construct）对象的过程称为创建这个类的一个实例（instance）。用Java编写的所有代码都在某个类中。</p>
            <p>封装（encapsulation）是将数据和行为组合在一个包中，并对对象的使用者隐藏具体的实现细节。对象中的数据称为实例字段（instance field）。操作数据的过程称为方法（method），作为一个类的实例，一个特定对象有一组特定的实例字段值。这些值的集合就是这个对象的当前状态（state），在对象上调用一个方法，它的状态就有可能发生改变。</p>
            <p><strong>实现封装的关键在于，绝对不能让其他类中的方法直接访问这个类的实例字段，程序只能通过对象的方法与对象数据进行交互。</strong></p>
            <p>扩展一个已有的类时，这个新类具有被扩展的那个类的全部属性和方法，只需要在新类中提供适用于这个新类的新方法和实例字段，通过扩展一个类来得到另外一个类的概念称为继承（inheritance）。            </p>
            <h3 class="title">类之间的关系</h3>
            <p><strong>依赖（uses-a）</strong>：如果一个类的方法要使用或操作另一个类的对象，我们就说前一个类依赖于后一个类。</p>
            <p><strong>聚合（has-a）</strong>：包含关系意味着类A的对象包含类B的对象。</p>
            <p><strong>继承（is-a）</strong>：表示一个更特殊的类与一个更一般的类之间的关系。</p>
            <p>对象变量并不实际包含一个对象，它只是引用一个对象。任何对象变量的值都是一个引用，指向存储在另外一个地方的某个对象。</p>
            <p>LocalDate的使用：</p>
            <pre><code>LocalDate date = LocalDate.now();
System.out.println("curr date：" + date.getYear() + "/" + date.getMonthValue() + "/" + date.getDayOfMonth());
date = date.plusDays(1);
System.out.println("curr date：" + date.getYear() + "/" + date.getMonthValue() + "/" + date.getDayOfMonth());</code></pre>
            <p>var关键字（Java 10）只能用于方法中的局部变量，参数和字段的类型必须声明。</p>
            <pre><code>Employee harry = new Employee("Harry Hacker", 5000, 1989, 10, 1);
// 替代写法
var harry = new Employee("Harry Hacker", 5000, 1989, 10, 1);</code></pre>
            <p>如果类中的所有方法都不会改变其对象，这样的类就是不可变类。</p>
            <p>将实例字段定义为final，这样的字段必须在构造对象时初始化，final修饰符对于类型为基本类型或者不可变类的字段尤其有用。确保在每一个构造器执行之后，这个字段的值已经设置，并旦以后不能再修改这个字段。</p>
            <p>静态字段属于类，而不属于单个对象，每个静态字段只有一个副本。</p>
            <p>静态常量：</p>
            <pre><code>class Math {
    public static final double E = 2.71828182845904523536;
}</code></pre>
            <p>类的静态方法不能访问实例字段，因为富并不操作对象，静态方法可以访问静态字段。main方法也是一个静态方法，每一个类都可以有一个main方法。</p>
            <p>Java程序设计语言总是采用按值调用。不过，有两种不同类型的方法参数：基本数据类型与对象引用。</p>
            <p>如果多个方法有相同的方法名但有不同的参数, 便出现了<strong>重载</strong>。编译器用各个方法首部中的参数类型与特定方法调用中所使用的值类型进行匹配，来选出正确的方法。返回类型不是方法签名的一部分。不能有两个名字相同、参数类型也相同却有不同返回类型的方法。</p>
            <p>如果在构造器中没有显式地为一个字段设置初始值，就会将它自动设置为默认值：数值将设置为0，布尔值为false，对象引用为null。</p>
            <p>如果你写的类没有构造器，就会为你提供一个无参数构造器。这个构造器将所有的实例字段设置为相应的默认值。如果类中提供了至少一个构造器，但是没有提供无参数构造器，那么构造对象时就必须提供参数，否则就是不合法的。<strong>仅当类没有任何其他构造器的时候，你才会得到一个默认的无参数构造器。</strong></p>
            <p><em>初始化块</em>：在一个类的声明中，可以包含任意的代码块: 构造这个类的对象时，这些块就会执行：</p>
            <pre><code>public class Test{
    private int a;

    {
        a = 123;
        System.out.println("init block");
    }
}</code></pre>
            <p>首先运行初始化块，然后才运行构造器的主体部分。</p>
            <h3 class="title">记录</h3>
            <p>记录（record）是一种特殊形式的类（JDK16发布），其状态不可变，而且公共可读。每个记录有3个自动定义的方法：toString、equals和hashCode。</p>
            <pre><code>record Point(double x, double y) {}
Point p = new Point(3.0, 4.0);
System.out.println(p.x() + " " + p.y());</code></pre>
            <p>与所有其他类一样，记录可以有静态字段和方法，不过，不能为记录增加实例字段：</p>
            <pre><code>record Point(double x, double y) {
    private double r; // error
}</code></pre>
            <p>记录的实例字段自动为final字段。记兼更易读、更 高效，而且在并发程序中是安全。</p>
            <h3 class="title">包</h3>
            <p>使用包（package）将类组织在一个集合中，使用包的主要原因是确保类名的唯一性。为了保证包名的绝对唯一性，可以使用一个因特网域名（这显然是唯一的）以逆序的形式作为包名，然后对于不同的项目使用不同的子包。</p>
            <p>一个类可以使用所属包（这个类所在的包）中的所有类，以及其他包中的公共类。</p>
            <p>静态导入：有一种 import 语句允许导入静态方法和静态字段，而不只是类，</p>
            <pre><code>import static java.lang.System.*;
out.println('Goodbye World!');</code></pre>
            <p>要想将类放入包中，就必须将包名放在源文件的开头，即放在定义这个包中各个类的代码之前。如果没有在源文件中放置package语句，那么这个源文件中的类就属于无名包。无名包没有包名。</p>
            <p>如果包与目录不匹配，虚拟机就找不到这些类。类文件也可以存储在JAR（Java归档）文件中，在一个JAR文件中, 可以包含多个压缩格式的类文件和子目录，这样既可以节省空间又可以改善性能。</p>
            <h3 class="title">类设计技巧</h3>
            <p>一定要保证数据私有；一定要初始化敷据；不要在类中使用过多的基本类型；不是所有的字段都需要单独的字段访问器和更改器；分解有过多职责的类；类名和方法名要能够体现它们的职责；优先使用不可变的类。</p>
        </div>
    </MyArticle>
</template>
